package com.taoz.mianshiwa.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.taoz.mianshiwa.common.ErrorCode;
import com.taoz.mianshiwa.constant.SortOrder;
import com.taoz.mianshiwa.exception.ThrowUtils;
import com.taoz.mianshiwa.mapper.QuestionBankQuestionMapper;
import com.taoz.mianshiwa.model.dto.questionBankQuestion.QuestionBankQuestionQueryRequest;
import com.taoz.mianshiwa.model.entity.Question;
import com.taoz.mianshiwa.model.entity.QuestionBank;
import com.taoz.mianshiwa.model.entity.QuestionBankQuestion;
import com.taoz.mianshiwa.model.entity.User;
import com.taoz.mianshiwa.model.vo.QuestionBankQuestionVO;
import com.taoz.mianshiwa.model.vo.UserVO;
import com.taoz.mianshiwa.service.QuestionBankQuestionService;
import com.taoz.mianshiwa.service.QuestionBankService;
import com.taoz.mianshiwa.service.QuestionService;
import com.taoz.mianshiwa.service.UserService;
import com.taoz.mianshiwa.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 题库服务实现
 *
 * @author <a href="https://github.com/liyupi">程序员鱼皮</a>
 * @from <a href="https://www.code-nav.cn">编程导航学习圈</a>
 */
@Service
@Slf4j
public class QuestionBankQuestionServiceImpl extends ServiceImpl<QuestionBankQuestionMapper, QuestionBankQuestion> implements QuestionBankQuestionService {

    @Resource
    private UserService userService;
    @Resource
    private QuestionBankService questionBankService;
    @Resource
    private QuestionService questionService;
    @Resource
    private QuestionBankQuestionService questionBankQuestionService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchDeleteQuestionsFromBank(Long questionBankId, List<Long> questionIdList) {
        // 数据校验
        ThrowUtils.throwIf(questionBankId == null || questionBankId <= 0, ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(CollUtil.isEmpty(questionIdList), ErrorCode.PARAMS_ERROR);
        QuestionBank questionBank = questionBankService.getById(questionBankId);
        ThrowUtils.throwIf(questionBank == null, ErrorCode.NOT_FOUND_ERROR);

        // 构造删除
        LambdaQueryWrapper<QuestionBankQuestion> questionBankQuestionQueryWrapper = new LambdaQueryWrapper<>();
        questionBankQuestionQueryWrapper
                .eq(QuestionBankQuestion::getQuestionBankId, questionBankId)
                .in(QuestionBankQuestion::getQuestionId, questionIdList);
        remove(questionBankQuestionQueryWrapper);
    }

    @Override
    public Page<QuestionBankQuestionVO> getQuestionBankQuestionVOPage(Page<QuestionBankQuestion> questionBankQuestionPage, HttpServletRequest request) {
            List<QuestionBankQuestion> questionBankQuestionList = questionBankQuestionPage.getRecords();
            Page<QuestionBankQuestionVO> questionBankQuestionVOPage = new Page<>(questionBankQuestionPage.getCurrent(), questionBankQuestionPage.getSize(), questionBankQuestionPage.getTotal());
            if (CollUtil.isEmpty(questionBankQuestionList)) {
                return questionBankQuestionVOPage;
            }
            // 对象列表 => 封装对象列表
            List<QuestionBankQuestionVO> questionBankQuestionVOList = questionBankQuestionList.stream().map(QuestionBankQuestionVO::objToVo).collect(Collectors.toList());

            questionBankQuestionVOPage.setRecords(questionBankQuestionVOList);
            return questionBankQuestionVOPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchAddQuestionsToBank(Long questionBankId, List<Long> questionIdList) {
        // 数据校验
        ThrowUtils.throwIf(questionBankId == null || questionBankId <= 0, ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(CollUtil.isEmpty(questionIdList), ErrorCode.PARAMS_ERROR);
        QuestionBank questionBank = questionBankService.getById(questionBankId);
        ThrowUtils.throwIf(questionBank == null, ErrorCode.NOT_FOUND_ERROR);

        // 构造插入

        // 排除了questionId不存在的情况
        List<Long> existQuestionIdList = questionService.lambdaQuery()
                .select(Question::getId).in(Question::getId, questionIdList).list()
                .stream().map(Question::getId).collect(Collectors.toList());
        ThrowUtils.throwIf(CollUtil.isEmpty(existQuestionIdList), ErrorCode.PARAMS_ERROR);

        // 求出了已经在题库中的id
        Set<Long> invalidQuestionIdList = questionBankQuestionService.lambdaQuery()
                .select(QuestionBankQuestion::getQuestionId)
                .eq(QuestionBankQuestion::getQuestionBankId, questionBankId)
                .in(QuestionBankQuestion::getQuestionId, existQuestionIdList)
                .list().stream().map(QuestionBankQuestion::getQuestionId).collect(Collectors.toSet());

        ArrayList<QuestionBankQuestion> saveData = new ArrayList<>();
        for (Long questionId : questionIdList) {
            if (!invalidQuestionIdList.contains(questionId)) {
                saveData.add(new QuestionBankQuestion(questionBankId, questionId, StpUtil.getLoginIdAsLong()));
            }
        }

        ThrowUtils.throwIf(CollUtil.isEmpty(saveData), ErrorCode.PARAMS_ERROR, "加入失败");
        saveBatch(saveData);
    }

    /**
     * 校验数据
     *
     * @param questionBankQuestion
     * @param add      对创建的数据进行校验
     */
    @Override
    public void validQuestionBankQuestion(QuestionBankQuestion questionBankQuestion, boolean add) {
        ThrowUtils.throwIf(questionBankQuestion == null, ErrorCode.PARAMS_ERROR);
    }

    /**
     * 获取查询条件
     *
     * @param questionBankQuestionQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<QuestionBankQuestion> getQueryWrapper(QuestionBankQuestionQueryRequest questionBankQuestionQueryRequest) {
        QueryWrapper<QuestionBankQuestion> queryWrapper = new QueryWrapper<>();
        if (questionBankQuestionQueryRequest == null) {
            return queryWrapper;
        }
        // todo 从对象中取值
        String sortField = questionBankQuestionQueryRequest.getSortField();
        String sortOrder = questionBankQuestionQueryRequest.getSortOrder();
        Long userId = questionBankQuestionQueryRequest.getUserId();
        Long questionBankId = questionBankQuestionQueryRequest.getQuestionBankId();
        Long questionId = questionBankQuestionQueryRequest.getQuestionId();
        // todo 补充需要的查询条件

        // 模糊查询
        // JSON 数组查询
        // 精确查询
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(questionBankId), "questionBankId", questionBankId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(questionId), "questionId", questionId);
        // 排序规则
        queryWrapper.orderBy(SqlUtils.validSortField(sortField),
                sortOrder.equals(SortOrder.ASC),
                sortField);
        return queryWrapper;
    }

    /**
     * 获取题库封装
     *
     * @param questionBankQuestion
     * @param request
     * @return
     */
    @Override
    public QuestionBankQuestionVO getQuestionBankQuestionVO(QuestionBankQuestion questionBankQuestion, HttpServletRequest request) {
        return QuestionBankQuestionVO.objToVo(questionBankQuestion);
    }

}
